package top.chukongxiang.monitorservice.components;

import com.sun.jna.Pointer;
import com.sun.jna.ptr.ByteByReference;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import top.chukongxiang.monitorservice.config.SdkServerContextHolder;
import top.chukongxiang.monitorservice.jna.HCNetSDK;
import top.chukongxiang.monitorservice.model.exception.FxException;

/**
 * @author 楚孔响
 * @version 1.0
 * @date 2023/11/2 17:50
 */
@Slf4j
@RequiredArgsConstructor
public class PreviewCallbackHandler implements HCNetSDK.FRealDataCallBack_V30 {

    @Getter
    private final Long serverId;

    private final PreviewDataHandler previewDataHandler;

    @Override
    public void invoke(int lRealHandle, int dwDataType, ByteByReference pBuffer, int dwBufSize, Pointer pUser) {

        if (!SdkServerContextHolder.isPlaying(serverId)) {
            SdkServerContextHolder.setPlay(serverId, lRealHandle);
        }

        switch (dwDataType) {
            // 系统头数据
            case HCNetSDK.NET_DVR_SYSHEAD: {
                if (dwBufSize > 0) {
                    Pointer pointer = pBuffer.getPointer();
                    if (pointer != null && previewDataHandler != null) {
                        try {
                            previewDataHandler.writeSysHeader(pointer.getByteArray(0, dwBufSize));
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                            // TODO 这里应该停止预览
                            stop();
                            throw new FxException(e);
                        }
                    }
                }
                break;
            }
            case HCNetSDK.NET_DVR_STREAMDATA: {
                if (dwBufSize > 0) {
                    // 码流数据
                    Pointer pointer = pBuffer.getPointer();
                    if (pointer != null && previewDataHandler != null) {
                        try {
                            previewDataHandler.writeVideo(pointer.getByteArray(0, dwBufSize));
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                            // TODO 这里应该停止预览
                            stop();
                            throw new FxException(e);
                        }
                    }
                }
                break;
            }
            // 音频码流数据
            case HCNetSDK.NET_DVR_AUDIOSTREAMDATA: {
                if (dwBufSize > 0) {
                    Pointer pointer = pBuffer.getPointer();
                    try {
                        if (pointer != null && previewDataHandler != null) {
                            try {
                                previewDataHandler.writeAudio(pointer.getByteArray(0, dwBufSize));
                            } catch (Exception e) {
                                log.error(e.getMessage(), e);
                                stop();
                                return;
                            }
                        }
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                        throw new FxException(e);
                    }
                }
                break;
            }
            //预览异常
            case HCNetSDK.NET_DVR_REALPLAYEXCEPTION:
            //预览时连接断开
            case HCNetSDK.NET_DVR_REALPLAYNETCLOSE:
            //预览5s没有收到数据
            case HCNetSDK.NET_DVR_REALPLAY5SNODATA:
            //回放异常
            case HCNetSDK.NET_DVR_PLAYBACKEXCEPTION:
            //回放时候连接断开
            case HCNetSDK.NET_DVR_PLAYBACKNETCLOSE:
            //回放5s没有收到数据
            case HCNetSDK.NET_DVR_PLAYBACK5SNODATA:
            default: {
                log.warn("{} 流预览停止：{}", serverId, dwDataType);
                stop();
                break;
            }
        }
    }

    public void stop() {
        log.warn("结束预览：{}", serverId);
        SdkServerContextHolder.setPlay(serverId, null);
    }

}
